package cn.jhz.learn.blog.service.core.auth.file.impl;

import cn.jhz.learn.blog.common.exception.ParamException;
import cn.jhz.learn.blog.common.util.EncodeUtil;
import cn.jhz.learn.blog.dao.file.BlogFileMapper;
import cn.jhz.learn.blog.po.file.BlogFile;
import cn.jhz.learn.blog.po.file.BlogFileContent;
import cn.jhz.learn.blog.service.core.auth.file.ConsoleFileService;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

@Service("consolePhotoService")
public class ConsoleFileServiceImpl implements ConsoleFileService {

    private final BlogFileMapper fileMapper;

    @Autowired
    public ConsoleFileServiceImpl(BlogFileMapper fileMapper) {
        this.fileMapper = fileMapper;
    }

    @Override
    public Map<String, BlogFile> batchUpload(List<MultipartFile> files) {
        Map<String, BlogFile> tempFileMap = Maps.newHashMap();
        Map<String, String> tempFileNameMap = Maps.newHashMap();
        Map<String, BlogFileContent> tempFileContentMap = Maps.newHashMap();
        List<BlogFile> isExistFile;

        try {
            String signatureCode;
            byte[] content;
            for (MultipartFile temp : files) {
                content = temp.getBytes();
                signatureCode = EncodeUtil.signatureCode(content);

                tempFileMap.put(temp.getOriginalFilename(),
                        BlogFile.builder().status((byte)1).signatureCode(signatureCode).size((int) temp.getSize()).type(temp.getContentType()).build());
                tempFileContentMap.put(temp.getOriginalFilename(), new BlogFileContent(content));
                tempFileNameMap.put(signatureCode, temp.getOriginalFilename());
            }
        } catch (IOException | NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        isExistFile = fileMapper.selectBySignatureCode(Lists.newArrayList(tempFileNameMap.keySet()));

        List<String> unLegalFiles = isExistFile.stream()
                .filter(temp -> temp.getStatus().equals((byte)0))
                .map(BlogFile::getSignatureCode)
                .map(tempFileNameMap::get)
                .collect(toList());

        if(!unLegalFiles.isEmpty())
            throw new ParamException("不合法文件["+unLegalFiles+"]");

        /*清除列表中已存在的文件*/
        Iterator<Map.Entry<String, String>> iterator = tempFileNameMap.entrySet().iterator();
        Map.Entry<String, String> entry;
        List<String> isExistFileSignatureCode = isExistFile.stream().map(BlogFile::getSignatureCode).collect(toList());
        while(iterator.hasNext()){
            entry = iterator.next();
            if(isExistFileSignatureCode.remove(entry.getKey())) {
                tempFileMap.remove(entry.getValue());
                tempFileContentMap.remove(entry.getValue());
            }
        }
        if(!tempFileMap.isEmpty())
            insertFile(tempFileMap, tempFileContentMap);

        Map<String, BlogFile> resuleMap = Maps.newHashMap(isExistFile.stream().collect(toMap(e->tempFileNameMap.get(e.getSignatureCode()), e -> e)));
        resuleMap.putAll(tempFileMap);

        return resuleMap;
    }

    @Override
    public List<BlogFile> batchUploadPicture(List<MultipartFile> files) {
        Map<String, BlogFile> filesMap = batchUpload(files);
        return files.stream().map(MultipartFile::getOriginalFilename).map(filesMap::get).collect(toList());
    }

    @Transactional
    public void insertFile(@NotNull Map<String, BlogFile> tempFileMap,
                           @NotNull Map<String, BlogFileContent> tempFileContentMap){
        fileMapper.batchInsert(Lists.newArrayList(tempFileMap.values()));
        //批量插入文件实体
        tempFileMap.keySet().forEach(e -> tempFileContentMap.get(e).setId(tempFileMap.get(e).getId()));
        //设置内容主键
        fileMapper.batchInsertContent(Lists.newArrayList(tempFileContentMap.values()));
        //批量插入文件内容
    }
}
